
(function () {
    var TABLE_HEIGHT_ADJUST = (dorado.Browser.msie) ? -1 : 0;
    dorado.widget.RowList = $extend(dorado.widget.ViewPortList, {$className:"dorado.widget.RowList", ATTRIBUTES:{rowHeight:{defaultValue:dorado.Browser.isTouch ? ($setting["touch.ListBox.defaultRowHeight"] || 30) : ($setting["widget.ListBox.defaultRowHeight"] || 22)}, highlightCurrentRow:{defaultValue:true, skipRefresh:true, setter:function (v) {
        this._highlightCurrentRow = v;
        if (this._currentRow) {
            $fly(this._currentRow).toggleClass("current-row", !!v);
        }
    }}, highlightHoverRow:{defaultValue:true}, highlightSelectedRow:{defaultValue:true}, useNativeScrollbars:{}}, EVENTS:{onDataRowClick:{}, onDataRowDoubleClick:{}}, _constructor:function () {
        $invokeSuper.call(this, arguments);
        if (this._itemModel) {
            this._itemModel.setItemDomSize(this._rowHeight);
        }
    }, getIndexByItemId:function (itemId) {
        if (typeof itemId == "number") {
            return itemId;
        } else {
            var itemModel = this._itemModel;
            return itemModel.getItemIndex(itemModel.getItemById(itemId));
        }
    }, getCurrentItemDom:function () {
        return this._currentRow;
    }, getDraggableOptions:function (dom) {
        var options = $invokeSuper.call(this, arguments);
        if (dom == this._dom) {
            options.handle = ":first-child";
        }
        return options;
    }, createDataTable:function () {
        var table = this._dataTable = $DomUtils.xCreate({tagName:"TABLE", cellSpacing:0, cellPadding:0, className:"data-table", content:{tagName:"TBODY"}});
        var tbody = this._dataTBody = table.tBodies[0];
        var self = this;
        $fly(table).mouseover(function (evt) {
            if ($DomUtils.isDragging() || !self._highlightHoverRow) {
                return;
            }
            dorado.Toolkits.cancelDelayedAction(self, "$hoverOutTimerId");
            self.setHoverRow(self.findItemDomByEvent(evt));
        }).mouseout(function (evt) {
            dorado.Toolkits.setDelayedAction(self, "$hoverOutTimerId", function () {
                self.setHoverRow(null);
            }, 50);
        });
        return table;
    }, findItemDomByEvent:function (evt) {
        var target = evt.srcElement || evt.target;
        var target = target || evt, tbody = this._dataTBody;
        return $DomUtils.findParent(target, function (parentNode) {
            return parentNode.parentNode == tbody;
        });
    }, onMouseDown:function (evt) {
        var row = this.findItemDomByEvent(evt);
        if (row || this._allowNoCurrent) {
            if (row && evt.shiftKey) {
                $DomUtils.disableUserSelection(row);
            }
            var oldCurrentItem = this.getCurrentItem();
            if (this.setCurrentItemDom(row)) {
                var clickedItem = (row ? $fly(row).data("item") : null), selection = this.getSelection();
                if (this._selectionMode == "singleRow") {
                    if (evt.ctrlKey || evt.shiftKey) {
                        this.replaceSelection(null, clickedItem);
                    }
                } else {
                    if (this._selectionMode == "multiRows") {
                        var removed = [], added = [];
                        if (evt.altKey || evt.ctrlKey && evt.shiftKey) {
                            removed = selection;
                        } else {
                            if (evt.ctrlKey) {
                                this.addOrRemoveSelection(selection, clickedItem, removed, added);
                            } else {
                                if (evt.shiftKey) {
                                    var si = -1, ei, itemModel = this._itemModel;
                                    if (oldCurrentItem) {
                                        si = itemModel.getItemIndex(oldCurrentItem);
                                    }
                                    if (oldCurrentItem) {
                                        if (si < 0) {
                                            si = itemModel.getItemIndex(oldCurrentItem);
                                        }
                                        ei = itemModel.getItemIndex(clickedItem);
                                        if (si > ei) {
                                            var i = si;
                                            si = ei, ei = i;
                                        }
                                        removed = selection.slice(0);
                                        removed.remove(oldCurrentItem);
                                        removed.remove(clickedItem);
                                        selection = [];
                                        var c = ei - si + 1, i = 0;
                                        var it = itemModel.iterator(si);
                                        while (it.hasNext() && i < c) {
                                            added.push(it.next());
                                            i++;
                                        }
                                    } else {
                                        this.addOrRemoveSelection(selection, clickedItem, removed, added);
                                    }
                                }
                            }
                        }
                        this.replaceSelection(removed, added);
                    }
                }
            }
            if (dorado.Browser.msie) {
                var tbody = this._dataTBody;
                try {
                    var cell = $DomUtils.findParent(evt.target, function (parentNode) {
                        return parentNode.parentNode.parentNode == tbody;
                    }, true);
                    if (cell) {
                        ((cell.firstChild && cell.firstChild.nodeType == 1) ? cell.firstChild : cell).focus();
                    }
                }
                catch (e) {
                    try {
                        evt.target.focus();
                    }
                    catch (e) {
                    }
                }
            }
        }
    }, getSelection:function () {
        var selection = this._selection;
        if (this._selectionMode == "multiRows") {
            if (!selection) {
                selection = [];
            }
        }
        return selection;
    }, setSelection:function (selection) {
        this._selection = selection;
    }, replaceSelection:function (removed, added, silence) {
        if (removed == added) {
            return;
        }
        switch (this._selectionMode) {
          case "singleRow":
            removed = this.get("selection");
            break;
          case "multiRows":
            if (removed instanceof Array && removed.length == 0) {
                removed = null;
            }
            if (added instanceof Array && added.length == 0) {
                added = null;
            }
            if (removed == added) {
                return;
            }
            if (removed && !(removed instanceof Array)) {
                removed = [removed];
            }
            if (added && !(added instanceof Array)) {
                added = [added];
            }
            break;
        }
        var eventArg = {removed:removed, added:added};
        if (!silence) {
            this.fireEvent("beforeSelectionChange", this, eventArg);
            removed = eventArg.removed;
            added = eventArg.added;
        }
        switch (this._selectionMode) {
          case "singleRow":
            if (removed) {
                this.toggleItemSelection(removed, false);
            }
            if (added) {
                this.toggleItemSelection(added, true);
            }
            this.setSelection(added);
            break;
          case "multiRows":
            var selection = this.get("selection");
            if (removed && selection) {
                if (removed == selection) {
                    removed = selection.slice(0);
                    for (var i = 0; i < selection.length; i++) {
                        this.toggleItemSelection(selection[i], false);
                    }
                    selection = null;
                } else {
                    for (var i = 0; i < removed.length; i++) {
                        selection.remove(removed[i]);
                        this.toggleItemSelection(removed[i], false);
                    }
                }
            }
            if (selection == null) {
                this.setSelection(selection = []);
            }
            if (added) {
                for (var i = 0; i < added.length; i++) {
                    if (selection.indexOf(added[i]) >= 0) {
                        continue;
                    }
                    selection.push(added[i]);
                    this.toggleItemSelection(added[i], true);
                }
            }
            this.setSelection(selection);
            break;
        }
        if (!silence) {
            eventArg.removed = removed;
            eventArg.added = added;
            this.fireEvent("onSelectionChange", this, eventArg);
        }
    }, addOrRemoveSelection:function (selection, clickedObj, removed, added) {
        if (!selection || selection.indexOf(clickedObj) < 0) {
            added.push(clickedObj);
        } else {
            removed.push(clickedObj);
        }
    }, toggleItemSelection:function (item, selected) {
        if (!this._highlightSelectedRow || !this._itemDomMap) {
            return;
        }
        var row = this._itemDomMap[this._itemModel.getItemId(item)];
        if (row) {
            $fly(row).toggleClass("selected-row", selected);
        }
    }, onClick:function (evt) {
        if (this.findItemDomByEvent(evt)) {
            this.fireEvent("onDataRowClick", this, {event:evt});
        }
    }, onDoubleClick:function (evt) {
        if (this.findItemDomByEvent(evt)) {
            this.fireEvent("onDataRowDoubleClick", this, {event:evt});
        }
    }, setHoverRow:function (row) {
        if (row) {
            if (this._draggable && this._dragMode != "control") {
                this.applyDraggable(row);
            }
            $fly(row).addClass("hover-row");
        }
        if (this._hoverRow == row) {
            return;
        }
        if (this._hoverRow) {
            $fly(this._hoverRow).removeClass("hover-row");
        }
        this._hoverRow = row;
    }, setCurrentRow:function (row) {
        if (this._currentRow == row) {
            return;
        }
        this.setHoverRow(null);
        if (this._currentRow) {
            $fly(this._currentRow).removeClass("current-row");
        }
        this._currentRow = row;
        if (row && this._highlightCurrentRow) {
            $fly(row).addClass("current-row");
        }
    }, getItemTimestamp:function (item) {
        return (item instanceof dorado.Entity) ? item.timestamp : -1;
    }, refreshItemDoms:function (tbody, reverse, fn) {
        if (this._scrollMode == "viewport") {
            this.setCurrentRow(null);
        }
        this._duringRefreshAll = true;
        this._selectionCache = this.get("selection");
        try {
            return $invokeSuper.call(this, arguments);
        }
        finally {
            delete this._selectionCache;
            this._duringRefreshAll = false;
        }
    }, getRealCurrentItemId:function () {
        return this.getCurrentItemId();
    }, refreshItemDom:function (tbody, item, index, prepend) {
        var row;
        if (index >= 0 && index < tbody.childNodes.length) {
            var i = index;
            if (prepend) {
                i = tbody.childNodes.length - i - 1;
            }
            row = tbody.childNodes[i];
            if (this._itemDomMap[row._itemId] == row) {
                delete this._itemDomMap[row._itemId];
            }
        } else {
            row = this.createItemDom(item);
            prepend ? tbody.insertBefore(row, tbody.firstChild) : tbody.appendChild(row);
        }
        var flag = prepend ? -1 : 1;
        if (index < 0) {
            flag = -flag;
        }
        index = this._itemModel.getStartIndex() + index * flag;
        var itemId = this._itemModel.getItemId(item, index);
        this._itemDomMap[itemId] = row;
        row.itemIndex = index;
        row._itemId = itemId;
        var $row = $fly(row);
        $row.data("item", item);
        if (!this._shouldSkipRender && row._lazyRender) {
            this.createItemDomDetail(row, item);
            row._lazyRender = undefined;
        }
        if (!row._lazyRender) {
            $row.toggleClass("odd-row", (!this._itemModel.groups && (index % 2) == 1));
            if (itemId == this.getRealCurrentItemId()) {
                this.setCurrentRow(row);
            }
            if (this._selectionMode != "none") {
                var selection = this._selectionCache || this.get("selection");
                switch (this._selectionMode) {
                  case "singleRow":
                    $row.toggleClass("selected-row", (selection == item) && this._highlightSelectedRow);
                    break;
                  case "multiRows":
                    $row.toggleClass("selected-row", !!(selection && selection.indexOf(item) >= 0) && this._highlightSelectedRow);
                    break;
                }
            }
            this.refreshItemDomData(row, item);
        }
        return row;
    }, refreshItemDomData:function (row, item) {
        if (row._lazyRender) {
            return;
        }
        var timestamp = this.getItemTimestamp(item);
        if (this._ignoreItemTimestamp || timestamp <= 0 || row.timestamp != timestamp) {
            this.doRefreshItemDomData(row, item);
            row.timestamp = timestamp;
        }
    }, refreshContent:function (container) {
        if (!this._dataTable) {
            var table = this.createDataTable();
            container.appendChild(table);
        }
        if (this._currentScrollMode == "viewport") {
            var beginBlankRow = this._beginBlankRow;
            var endBlankRow = this._endBlankRow;
            if (beginBlankRow) {
                beginBlankRow.parentNode.style.display = "none";
            }
            if (endBlankRow) {
                endBlankRow.parentNode.style.display = "none";
            }
            this._itemModel.setScrollPos(0);
        }
        var fn;
        if (this._scrollMode == "lazyRender" && container.clientHeight > 0) {
            var count = parseInt(container.clientHeight / this._rowHeight), i = 0;
            fn = function (row) {
                i++;
                return i <= count;
            };
        }
        this.refreshItemDoms(this._dataTBody, false, fn);
    }, refreshViewPortContent:function (container) {
        var beginBlankRow = this._beginBlankRow;
        var endBlankRow = this._endBlankRow;
        if (!this._dataTable) {
            container.appendChild(this.createDataTable());
        }
        if (!beginBlankRow) {
            this._beginBlankRow = beginBlankRow = $DomUtils.xCreate({tagName:"TR", className:"preparing-area", content:"^TD"});
            var thead = document.createElement("THEAD");
            thead.appendChild(beginBlankRow);
            container.firstChild.appendChild(thead);
        }
        if (!endBlankRow) {
            this._endBlankRow = endBlankRow = $DomUtils.xCreate({tagName:"TR", className:"preparing-area", content:"^TD"});
            var tfoot = document.createElement("TFOOT");
            tfoot.appendChild(endBlankRow);
            container.firstChild.appendChild(tfoot);
        }
        var tbody = this._dataTBody;
        var itemModel = this._itemModel, itemCount = itemModel.getItemCount();
        var clientHeight = (container.scrollWidth > container.clientWidth) ? container.offsetHeight : container.clientHeight;
        var viewPortHeight, itemDomCount, self = this;
        if (clientHeight) {
            viewPortHeight = TABLE_HEIGHT_ADJUST;
            itemDomCount = this.refreshItemDoms(tbody, itemModel.isReverse(), function (row) {
                viewPortHeight += row.offsetHeight;
                if (dorado.Browser.safari) {
                    viewPortHeight -= 2;
                }
                return viewPortHeight <= (clientHeight + 0);
            });
        } else {
            itemDomCount = viewPortHeight = 0;
        }
        this._itemDomCount = itemDomCount;
        if (!this._skipProcessBlankRows) {
            var startIndex = this.startIndex;
            var cols = this._cols || 1;
            var rowHeightAverage = (itemDomCount > 0) ? viewPortHeight / itemDomCount : this._rowHeight;
            with (beginBlankRow) {
                if (startIndex > 0) {
                    firstChild.colSpan = cols;
                    firstChild.style.height = Math.round(startIndex * rowHeightAverage) + "px";
                    parentNode.style.display = "";
                } else {
                    parentNode.style.display = "none";
                    firstChild.style.height = "0px";
                }
            }
            with (endBlankRow) {
                if ((itemDomCount + startIndex) < itemCount) {
                    firstChild.colSpan = cols;
                    firstChild.style.height = Math.round((itemCount - itemDomCount - startIndex) * rowHeightAverage) + "px";
                    parentNode.style.display = "";
                } else {
                    parentNode.style.display = "none";
                    firstChild.style.height = "0px";
                }
            }
            var st;
            if (this.startIndex >= itemModel.getStartIndex()) {
                st = this._dataTBody.offsetTop;
            } else {
                st = this._dataTBody.offsetTop + this._dataTBody.offsetHeight - container.clientHeight;
            }
            container.scrollTop = this._scrollTop = st;
            var scrollHeight = container.scrollHeight;
            itemModel.setScrollSize(container.clientHeight, scrollHeight);
            this._rowHeightAverage = rowHeightAverage;
        }
    }, onScroll:function (event, arg) {
        var rowList = this;
        if (rowList._scrollMode == "simple") {
            return;
        }
        var container = rowList._container;
        if ((rowList._scrollLeft || 0) != arg.scrollLeft) {
            if (rowList.onXScroll) {
                rowList.onXScroll(arg);
            }
        }
        if ((rowList._scrollTop || 0) != arg.scrollTop) {
            rowList.onYScroll(arg);
        }
        rowList._scrollLeft = arg.scrollLeft;
        rowList._scrollTop = arg.scrollTop;
    }, onYScroll:function (arg, fixedBug) {
        var container = this._container;
        if (arg.scrollTop == (container._scrollTop || 0)) {
            return;
        }
        if (this._scrollMode == "viewport") {
            if (dorado.Toolkits.cancelDelayedAction(container, "$scrollTimerId")) {
                if (Math.abs(arg.scrollTop - container._scrollTop) > (arg.clientHeight / 4)) {
                    var itemCount = this._itemModel.getItemCount();
                    var rowHeight = arg.scrollHeight / itemCount;
                    this.setScrollingIndicator((Math.round(arg.scrollTop / rowHeight) + 1) + "/" + itemCount);
                }
            } else {
                container._scrollTop = arg.scrollTop;
            }
            if (!fixedBug) {
                var self = this;
                dorado.Toolkits.setDelayedAction(container, "$scrollTimerId", function () {
                    self.doOnYScroll(arg);
                }, 300);
            }
        } else {
            container._scrollTop = arg.scrollTop;
            if (!fixedBug) {
                this.doOnYScroll(arg);
            }
        }
    }, doOnYScroll:function (arg) {
        if (this._scrollMode == "viewport") {
            dorado.Toolkits.cancelDelayedAction(this._container, "$scrollTimerId");
            this._itemModel.setScrollPos(arg.scrollTop);
            this.setHoverRow(null);
            this.refresh();
            this.hideScrollingIndicator();
        } else {
            if (this._scrollMode == "lazyRender") {
                var rows = this._dataTBody.rows;
                var i = parseInt(arg.scrollTop / this._rowHeight) || 0;
                if (i >= rows.length) {
                    i = rows.length - 1;
                }
                var row = rows[i];
                if (!row) {
                    return;
                }
                while (row && row.offsetTop > arg.scrollTop) {
                    i--;
                    row = rows[i];
                }
                var bottom = arg.scrollTop + arg.clientHeight;
                while (row && row.offsetTop < bottom) {
                    if (row._lazyRender) {
                        var item = $fly(row).data("item");
                        this.createItemDomDetail(row, item);
                        row._lazyRender = undefined;
                        this.refreshItemDomData(row, item);
                    }
                    i++;
                    row = rows[i];
                }
            }
        }
    }, createDom:function () {
        var dom = $invokeSuper.call(this, arguments);
        if (dorado.Browser.msie && dorado.Browser.version >= 8) {
            dom.hideFocus = true;
        }
        if (this._useNativeScrollbars) {
            $fly(this._container).css("overflow", "auto");
        } else {
            $fly(this._container).bind("modernScrolled", $scopify(this, this.onScroll));
        }
        return dom;
    }, refreshDom:function (dom) {
        var hasRealWidth = !!this._width, hasRealHeight = !!this._height, oldWidth, oldHeight;
        if (!hasRealWidth || !hasRealHeight) {
            oldWidth = dom.offsetWidth;
            oldHeight = dom.offsetHeight;
        }
        $invokeSuper.call(this, arguments);
        var container = this._container;
        if (this._scrollMode == "viewport") {
            this.refreshViewPortContent(container);
        } else {
            this.refreshContent(container);
        }
        if (this._currentScrollMode && this._currentScrollMode != this._scrollMode && !this.getCurrentItemId()) {
            this.doOnYScroll(container);
        }
        this._currentScrollMode = this._scrollMode;
        if (!this._skipScrollCurrentIntoView) {
            if (this._currentRow) {
                this.scrollItemDomIntoView(this._currentRow);
            } else {
                this.scrollCurrentIntoView();
            }
        }
        delete this._skipScrollCurrentIntoView;
        if ((!hasRealWidth || !hasRealHeight) && (oldWidth != dom.offsetWidth || oldHeight != dom.offsetHeight)) {
            this.notifySizeChange();
        }
        delete this._ignoreItemTimestamp;
    }, scrollItemDomIntoView:function (row) {
        with (this._container) {
            var st = -1;
            if ((row.offsetTop + row.offsetHeight) > (scrollTop + clientHeight)) {
                st = row.offsetTop + row.offsetHeight - clientHeight;
            } else {
                if (row.offsetTop < scrollTop) {
                    st = row.offsetTop;
                }
            }
            if (st >= 0) {
                if (this._scrollMode != "lazyRender") {
                    this._scrollTop = st;
                }
                scrollTop = st;
            }
        }
    }, scrollCurrentIntoView:function () {
        var currentItemId = this.getRealCurrentItemId();
        if (currentItemId != null) {
            var row = this._currentRow;
            if (row) {
                this.scrollItemDomIntoView(row);
            } else {
                if (this._scrollMode == "viewport") {
                    var itemModel = this._itemModel;
                    var index = this.getIndexByItemId(currentItemId);
                    if (index < 0) {
                        index = 0;
                    }
                    itemModel.setStartIndex(index);
                    var oldReverse = itemModel.isReverse();
                    itemModel.setReverse(index >= this.startIndex);
                    this.refresh();
                    itemModel.setReverse(oldReverse);
                } else {
                    row = this._itemDomMap[currentItemId];
                    if (row) {
                        this.setCurrentItemDom(row);
                    }
                }
            }
        }
    }, findItemDomByPosition:function (pos) {
        var dom = this._dom, y = pos.y + dom.scrollTop, row = null;
        var rows = this._dataTBody.rows, rowHeight = this._rowHeightAverage || this._rowHeight, i;
        if (this._scrollMode == "viewport") {
            var relativeY = y;
            if (this._beginBlankRow) {
                relativeY -= this._beginBlankRow.offsetHeight;
            }
            i = parseInt(relativeY / rowHeight);
        } else {
            i = parseInt(y / rowHeight);
        }
        if (i < 0) {
            i = 0;
        } else {
            if (i >= rows.length) {
                i = rows.length - 1;
            }
        }
        row = rows[i];
        while (row) {
            if (row.offsetTop > y) {
                row = row.previousSibling;
            } else {
                if (row.offsetTop + row.offsetHeight < y) {
                    if (row.nextSibling) {
                        row = row.nextSibling;
                    } else {
                        row._dropY = y - row.offsetTop;
                        break;
                    }
                } else {
                    row._dropY = y - row.offsetTop;
                    break;
                }
            }
        }
        return row;
    }});
})();
dorado.widget.list.ListBoxRowRenderer = $extend(dorado.Renderer, {$className:"dorado.widget.list.ListBoxRowRenderer", render:function (dom, arg) {
    var item = arg.data, text;
    if (item != null) {
        if (arg.property) {
            if (item instanceof dorado.Entity) {
                text = item.getText(arg.property);
            } else {
                text = item[arg.property];
            }
        } else {
            if (!item.isEmptyItem) {
                text = item;
            }
        }
    }
    dom.innerText = (text === undefined || text === null) ? "" : text;
}});
dorado.widget.AbstractListBox = $extend(dorado.widget.RowList, {$className:"dorado.widget.AbstractListBox", ATTRIBUTES:{className:{defaultValue:"d-list-box"}, width:{defaultValue:200}, property:{setter:function (property) {
    this._property = property;
    this._ignoreItemTimestamp = true;
}}, renderer:{}}, EVENTS:{onRenderRow:{}}, doRefreshItemDomData:function (row, item) {
    var processDefault = true, arg = {dom:row.firstChild, data:item, property:this._property, processDefault:false};
    if (this.getListenerCount("onRenderRow")) {
        this.fireEvent("onRenderRow", this, arg);
        processDefault = arg.processDefault;
    }
    if (processDefault) {
        (this._renderer || $singleton(dorado.widget.list.ListBoxRowRenderer)).render(row.firstChild, arg);
    }
}, createItemDom:function (item) {
    var row = document.createElement("TR");
    row.className = "row";
    row.style.height = this._rowHeight + "px";
    if (this._scrollMode == "lazyRender" && this._shouldSkipRender) {
        row._lazyRender = true;
        row.style.height = this._rowHeight + "px";
    } else {
        this.createItemDomDetail(row, item);
    }
    return row;
}, createItemDomDetail:function (dom, item) {
    var cell = document.createElement("TD");
    dom.appendChild(cell);
}, getItemByEvent:function (event) {
    var row = this.findItemDomByEvent(event);
    return (row) ? $fly(row).data("item") : null;
}});
dorado.widget.ListBox = $extend(dorado.widget.AbstractListBox, {$className:"dorado.widget.ListBox", ATTRIBUTES:{currentIndex:{skipRefresh:true, defaultValue:-1, setter:function (index) {
    if (index >= this._itemModel.getItemCount()) {
        index = -1;
    }
    if (this._currentIndex == index) {
        return;
    }
    this._currentIndex = index;
    var row = this.getItemDomByItemIndex(index);
    this.setCurrentRow(row);
    this.scrollCurrentIntoView();
    if (!row) {
        row = this.getItemDomByItemIndex(index);
        this.setCurrentRow(row);
    }
    this.fireEvent("onCurrentChange", this);
}}, currentItem:{readOnly:true, getter:function () {
    return this.getCurrentItem();
}}, items:{setter:function (v) {
    this.set("selection", null);
    this._currentIndex = -1;
    this._itemModel.setItems(v);
}, getter:function () {
    return this._itemModel.getItems();
}}}, refreshDom:function (dom) {
    $invokeSuper.call(this, arguments);
    var currentIndex = this._currentIndex;
    if (currentIndex < 0 && !this._allowNoCurrent && this._itemModel.getItemCount()) {
        currentIndex = 0;
    }
    this.set("currentIndex", currentIndex);
}, getItemDomByItemIndex:function (index) {
    var itemModel = this._itemModel, row;
    if (index >= itemModel.getItemCount()) {
        index = -1;
    }
    var item = index >= 0 ? itemModel.getItemAt(index) : null;
    if (this._rendered && this._itemDomMap && index >= 0) {
        if (this._rowCache && $fly(this._rowCache).data("item") == item) {
            row = this._rowCache;
            delete this._rowCache;
        } else {
            row = this._itemDomMap[itemModel.getItemId(item)];
        }
    }
    return row;
}, getCurrentItem:function () {
    if (this._currentIndex >= 0) {
        return this._itemModel.getItemAt(this._currentIndex);
    }
}, getCurrentItemId:function () {
    return this._currentIndex;
}, doOnKeyDown:function (evt) {
    var retValue = true;
    switch (evt.keyCode || evt.which) {
      case 36:
        this.set("currentIndex", 0);
        break;
      case 35:
        this.set("currentIndex", this._itemModel.getItemCount() - 1);
        break;
      case 38:
        if (this._currentIndex > 0) {
            this.set("currentIndex", this._currentIndex - 1);
        }
        retValue = false;
        break;
      case 40:
        if (this._currentIndex < this._itemModel.getItemCount() - 1) {
            this.set("currentIndex", this._currentIndex + 1);
        }
        retValue = false;
        break;
    }
    return retValue;
}, setCurrentItemDom:function (row) {
    this._rowCache = row;
    this.set("currentIndex", row ? this._itemModel.getItemIndex($fly(row).data("item")) : -1);
    return true;
}, highlightItem:function (index, options, speed) {
    if (index == undefined) {
        index = this._currentIndex;
    }
    var row = this.getItemDomByItemIndex(index);
    if (row) {
        $fly(row).addClass("highlighting-row").effect("highlight", options || {color:"#FF8000"}, speed || 1500, function () {
            $fly(row).removeClass("highlighting-row");
        });
    }
}});
dorado.widget.DataListBox = $extend([dorado.widget.AbstractListBox, dorado.widget.DataControl], {$className:"dorado.widget.DataListBox", ATTRIBUTES:{selection:{setter:function (selection) {
    this.refresh();
    $invokeSuper.call(this, arguments);
}}}, getCurrentItem:function () {
    return (this._currentRow) ? $fly(this._currentRow).data("item") : null;
}, getCurrentItemId:function (item, index) {
    var current = this.getCurrentItem();
    return current ? this._itemModel.getItemId(current) : null;
}, getRealCurrentItemId:function () {
    var current = this._itemModel.getItems() ? this._itemModel.getItems().current : null;
    return current ? this._itemModel.getItemId(current) : null;
}, setCurrentItemDom:function (row) {
    var item = (row ? $fly(row).data("item") : null);
    if (item) {
        var entityList = this._itemModel.getItems();
        entityList.setCurrent(item);
        if (entityList.current == item) {
            this.setCurrentEntity(item);
            return true;
        }
    }
    return false;
}, refreshEntity:function (entity) {
    var row = this._itemDomMap[this._itemModel.getItemId(entity)];
    if (row) {
        this.refreshItemDomData(row, entity);
    }
}, refreshDom:function (dom) {
    var entityList = this.getBindingData({firstResultOnly:true, acceptAggregation:true});
    if (entityList && !(entityList instanceof dorado.EntityList)) {
        throw new dorado.ResourceException(dorado.list.BindingTypeMismatch);
    }
    var oldItems = this._itemModel.getItems();
    if (oldItems != entityList) {
        this._itemModel.setItems(entityList);
        this.set("selection", null);
    }
    $invokeSuper.call(this, arguments);
}, setCurrentEntity:function (entity) {
    var currentItem = this._currentRow ? $fly(this._currentRow).data("item") : null;
    if (currentItem == entity) {
        return;
    }
    var itemId = entity ? this._itemModel.getItemId(entity) : null;
    var row = this._itemDomMap[itemId];
    this.setCurrentRow(row);
    this.scrollCurrentIntoView();
    this.fireEvent("onCurrentChange", this);
    return !!row;
}, doOnKeyDown:function (evt) {
    var retValue = true;
    var items = this._itemModel.getItems();
    switch (evt.keyCode) {
      case 36:
        items.first();
        break;
      case 35:
        items.last();
        break;
      case 38:
        items.previous();
        retValue = false;
        break;
      case 40:
        items.next();
        retValue = false;
        break;
    }
    return retValue;
}, _adjustBeginBlankRow:function () {
    this._ignoreOnScroll++;
    var itemModel = this._itemModel;
    var container = this.getDom();
    var beginBlankRow = this._beginBlankRow;
    var adj = container.scrollTop - beginBlankRow.offsetHeight;
    beginBlankRow.firstChild.style.height = this.startIndex * this._rowHeightAverage + "px";
    container.scrollTop = beginBlankRow.offsetHeight + adj;
    itemModel.setScrollSize(container.clientHeight, container.scrollHeight);
    $setTimeout(this, function () {
        this._ignoreOnScroll--;
    }, 0);
}, _adjustEndBlankRow:function () {
    var itemModel = this._itemModel;
    var container = this.getDom();
    var endBlankRow = this._endBlankRow;
    endBlankRow.firstChild.style.height = (itemModel.getItemCount() - this.startIndex - this.itemDomCount) * this._rowHeightAverage + "px";
    itemModel.setScrollSize(container.clientHeight, container.scrollHeight);
}, onEntityDeleted:function (arg) {
    var entity = arg.entity;
    this.replaceSelection(entity, null);
    var row = this._itemDomMap[this._itemModel.getItemId(entity)], tbody = this._dataTBody;
    if (this._scrollMode != "viewport") {
        if (row) {
            var nextRow = row.nextSibling;
            this.removeItemDom(row);
            if (this._forceRefreshRearRows !== false) {
                while (nextRow) {
                    this.refreshItemDom(tbody, $fly(nextRow).data("item"), nextRow.sectionRowIndex);
                    nextRow = nextRow.nextSibling;
                }
            }
            this.notifySizeChange();
        }
    } else {
        var itemModel = this._itemModel;
        if (row) {
            if (row == tbody.firstChild) {
                itemModel.setStartIndex(itemModel.getStartIndex() - 1);
                if (itemModel.getStartIndex() < 0) {
                    itemModel.setStartIndex(0);
                }
            } else {
                this.removeItemDom(row);
            }
            this.refresh();
        } else {
            var i = itemModel.getItemIndex(entity);
            if (i >= 0) {
                if (i < itemModel.getStartIndex()) {
                    this.startIndex--;
                    itemModel.setStartIndex(itemModel.getStartIndex() - 1);
                    this._adjustBeginBlankRow();
                } else {
                    this._adjustEndBlankRow();
                }
            }
        }
    }
}, onEntityInserted:function (arg) {
    function findFontNearestRow(entity) {
        var entity = entity.getPrevious(), row, itemDomMap = this._itemDomMap, itemModel = this._itemModel;
        while (entity) {
            row = itemDomMap[itemModel.getItemId(entity)];
            if (row) {
                return row;
            }
            entity = entity.getPrevious();
        }
    }
    function findBackNearestRow(entity) {
        var entity = entity.getNext(), row, itemDomMap = this._itemDomMap, itemModel = this._itemModel;
        while (entity) {
            row = itemDomMap[itemModel.getItemId(entity)];
            if (row) {
                return row;
            }
            entity = entity.getNext();
        }
    }
    var entity = arg.entity;
    var mode = arg.insertMode;
    var refEntity = arg.refEntity;
    var tbody = this._dataTBody, itemDomMap = this._itemDomMap, itemModel = this._itemModel;
    if (itemModel.filtered) {
        itemModel._items.push(entity);
    }
    if (this._scrollMode != "viewport") {
        var row;
        switch (mode) {
          case "begin":
            row = this.createItemDom(entity);
            tbody.insertBefore(row, tbody.firstChild);
            break;
          case "before":
            row = this.createItemDom(entity);
            var refRow = itemDomMap[itemModel.getItemId(refEntity)], inserted;
            if (!refRow) {
                refRow = findBackNearestRow.call(this, refEntity);
                if (!refRow) {
                    tbody.appendChild(row);
                    inserted = true;
                }
            }
            if (!inserted) {
                tbody.insertBefore(row, refRow);
            }
            break;
          case "after":
            row = this.createItemDom(entity);
            var refRow = itemDomMap[itemModel.getItemId(refEntity)], inserted;
            if (!refRow) {
                refRow = findFontNearestRow.call(this, refEntity);
                if (!refRow) {
                    tbody.insertBefore(row, tbody.firstChild);
                    inserted = true;
                }
            }
            if (!inserted) {
                if (refRow.nextSibling) {
                    tbody.insertBefore(row, refRow.nextSibling);
                } else {
                    tbody.appendChild(row);
                }
            }
            break;
          default:
            row = this.createItemDom(entity);
            tbody.appendChild(row);
        }
        this.refreshItemDom(tbody, entity, row.sectionRowIndex);
        if (this._forceRefreshRearRows != false) {
            row = row.nextSibling;
            while (row) {
                this.refreshItemDom(tbody, $fly(row).data("item"), row.sectionRowIndex);
                row = row.nextSibling;
            }
        }
        this.notifySizeChange();
    } else {
        var i = itemModel.getItemIndex(entity);
        if (i >= 0) {
            if (i < this.startIndex) {
                this.startIndex++;
                itemModel.setStartIndex(itemModel.getStartIndex() + 1);
            } else {
                if (i < this.startIndex + this.itemDomCount) {
                    var row = tbody.lastChild;
                    var nextRow = tbody.childNodes[i - this.startIndex];
                    tbody.insertBefore(row, nextRow);
                } else {
                    itemModel.setStartIndex(i - this.itemDomCount + 1);
                }
            }
            this.refresh();
        }
    }
}, filterDataSetMessage:function (messageCode, arg) {
    var itemModel = this._itemModel;
    var items = itemModel.getItems();
    switch (messageCode) {
      case dorado.widget.DataSet.MESSAGE_REFRESH:
        return true;
      case dorado.widget.DataSet.MESSAGE_CURRENT_CHANGED:
        return (!items || arg.entityList == items || dorado.DataUtil.isOwnerOf(items, arg.entityList));
      case dorado.widget.DataSet.MESSAGE_DATA_CHANGED:
      case dorado.widget.DataSet.MESSAGE_REFRESH_ENTITY:
        return (!items || items._observer != this._dataSet || arg.entity.parent == items || dorado.DataUtil.isOwnerOf(items, arg.entity));
      case dorado.widget.DataSet.MESSAGE_DELETED:
        return (arg.entity.parent == items || dorado.DataUtil.isOwnerOf(items, arg.entity));
      case dorado.widget.DataSet.MESSAGE_INSERTED:
        return (arg.entityList == items);
      case dorado.widget.DataSet.MESSAGE_ENTITY_STATE_CHANGED:
        return (arg.entity.parent == items);
      case dorado.widget.DataSet.MESSAGE_LOADING_START:
      case dorado.widget.DataSet.MESSAGE_LOADING_END:
        if (arg.entityList) {
            return (items == arg.entityList || dorado.DataUtil.isOwnerOf(items, arg.entityList));
        } else {
            if (arg.entity) {
                var asyncExecutionTimes = dorado.DataPipe.MONITOR.asyncExecutionTimes;
                this.getBindingData({firstResultOnly:true, acceptAggregation:true});
                if (dorado.DataPipe.MONITOR.asyncExecutionTimes > asyncExecutionTimes) {
                    return true;
                } else {
                    this.hideLoadingTip();
                    return false;
                }
            } else {
                return true;
            }
        }
      default:
        return false;
    }
}, processDataSetMessage:function (messageCode, arg, data) {
    switch (messageCode) {
      case dorado.widget.DataSet.MESSAGE_REFRESH:
        this.refresh(true);
        break;
      case dorado.widget.DataSet.MESSAGE_CURRENT_CHANGED:
        if (!this.setCurrentEntity(arg.entityList.current)) {
            this.refresh(true);
        }
        break;
      case dorado.widget.DataSet.MESSAGE_DATA_CHANGED:
      case dorado.widget.DataSet.MESSAGE_REFRESH_ENTITY:
        var items = this._itemModel.getItems();
        if (!items || items._observer != this._dataSet || arg.entity.parent == items || dorado.DataUtil.isOwnerOf(items, arg.newValue)) {
            this.refresh(true);
        } else {
            this.refreshEntity(arg.entity);
        }
        break;
      case dorado.widget.DataSet.MESSAGE_ENTITY_STATE_CHANGED:
        this.refreshEntity(arg.entity);
        break;
      case dorado.widget.DataSet.MESSAGE_DELETED:
        this.onEntityDeleted(arg);
        break;
      case dorado.widget.DataSet.MESSAGE_INSERTED:
        this.onEntityInserted(arg);
        break;
      case dorado.widget.DataSet.MESSAGE_LOADING_START:
        this.showLoadingTip();
        break;
      case dorado.widget.DataSet.MESSAGE_LOADING_END:
        this.hideLoadingTip();
        break;
    }
}, highlightItem:function (entity, options, speed) {
    entity = entity || this.getCurrentItem();
    var row = this._itemDomMap[this._itemModel.getItemId(entity)];
    if (row) {
        $fly(row).addClass("highlighting-row").effect("highlight", options || {color:"#FF8000"}, speed || 1500, function () {
            $fly(row).removeClass("highlighting-row");
        });
    }
}});

